package com.serene.authority.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.serene.authority.admin.annotation.DataPermission;
import com.serene.authority.admin.entity.vo.RoleVo;
import com.serene.authority.admin.entity.MyRole;
import com.serene.authority.admin.entity.MyRoleUser;
import com.serene.authority.admin.mapper.*;
import com.serene.authority.admin.service.RoleDeptService;
import com.serene.authority.admin.service.RoleMenuService;
import com.serene.authority.admin.service.RoleService;
import com.serene.authority.admin.service.RoleUserService;
import com.serene.authority.common.utils.Result;
import com.serene.authority.common.utils.ResultCode;
import com.serene.authority.common.utils.UserConstants;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.List;

import static cn.hutool.core.date.DateTime.now;

/**
 * @author serene
 * @createTime 2020/7/10
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, MyRole> implements RoleService {

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private RoleMenuMapper roleMenuMapper;

    @Autowired
    private RoleDeptMapper roleDeptMapper;

    @Autowired
    private RoleUserService roleUserService;

    @Autowired
    private RoleMenuService roleMenuService;

    @Autowired
    private RoleDeptService roleDeptService;

    @Override
    @DataPermission(deptAlias = "d")
    public Result<MyRole> getFuzzyRolesByPage(Integer offectPosition, Integer limit, MyRole myRole) {
        Page page = PageHelper.offsetPage(offectPosition, limit);
        List<MyRole> fuzzyRolesByPage = roleMapper.getFuzzyRolesByPage(myRole);
        return Result.ok().count(page.getTotal()).data(fuzzyRolesByPage).code(ResultCode.TABLE_SUCCESS);
    }

    @Override
    public MyRole getRoleById(Integer id) {
        QueryWrapper<MyRole> wrapper = new QueryWrapper<>();
        wrapper.eq("role_id", id);
        return roleMapper.selectOne(wrapper);
    }

    @Override
    public Result update(RoleVo roleDto) {
        List<Integer> menuIds = roleDto.getMenuIds();
        menuIds.remove(0L);
        //1、更新角色权限之前要删除该角色之前的所有权限
        roleMenuService.deleteRoleMenuByRoleId(roleDto.getRoleId());
        //2、判断该角色是否有赋予权限值，有就添加"
        if (!CollectionUtils.isEmpty(menuIds)) {
            roleMenuMapper.save(roleDto.getRoleId(), menuIds);
        }
        //3、更新角色表
        int countData = updateRole(roleDto);
        if (countData > 0) {
            return Result.ok().message("更新成功");
        } else {
            return Result.error().message("更新失败");
        }
    }

    @Override
    public Integer updateRole(MyRole roleVo) {
        UpdateWrapper<MyRole> wrapper = new UpdateWrapper<>();
        if (!StringUtils.isEmpty(roleVo.getRoleName())) {
            wrapper.eq("role_name", roleVo.getRoleName());
        }
        if (!StringUtils.isEmpty(roleVo.getDataScope())) {
            wrapper.eq("data_scope", roleVo.getDataScope());
        }
        if (!StringUtils.isEmpty(roleVo.getDescription())) {
            wrapper.eq("description", roleVo.getDescription());
        }
        roleVo.setUpdateTime(now());
        return roleMapper.update(roleVo, wrapper);
    }

    @Override
    public Result authDataScope(RoleVo roleDto) {
        if (roleDto.getDataScope().equals(UserConstants.DATA_SCOPE_CUSTOM)) {
            List<Integer> deptIds = roleDto.getDeptIds();
            deptIds.remove(0L);
            //通过角色id删除与部门关联
            roleDeptService.deleteRoleDeptByRoleId(roleDto.getRoleId());
            if (!CollectionUtils.isEmpty(deptIds)) {

                //新建角色与部门的联系
                roleDeptMapper.save(roleDto.getRoleId(), deptIds);
            }
            roleMapper.update(roleDto);
        } else {
            roleMapper.update(roleDto);
            //通过角色id删除与部门关联
            roleDeptService.deleteRoleDeptByRoleId(roleDto.getRoleId());
        }
        return Result.ok().message("更新成功");
    }

    @Override
    public Result save(RoleVo roleDto) {
        roleDto.setDataScope("1");
        //1、先保存角色"
        roleMapper.saveRole(roleDto);
        List<Integer> menuIds = roleDto.getMenuIds();
        //移除0,permission id是从1开始
        //2、保存角色对应的所有权限
        if (!CollectionUtils.isEmpty(menuIds)) {
            roleMenuMapper.save(roleDto.getRoleId(), menuIds);
        }
        return Result.ok().message("插入成功");
    }

    /**
     * 删除角色信息
     *
     * @param id 角色id
     * @return
     */
    @Override
    public Result<MyRole> delete(Integer id) {
        List<MyRoleUser> tbRoleUsers = roleUserService.queryRoleByUserByRoleId(id);
        if (tbRoleUsers.size() <= 0) {
            roleMenuService.deleteRoleMenuByRoleId(id);
            delRoleByRoleId(id);
            //通过角色id删除与部门关联
            roleDeptService.deleteRoleDeptByRoleId(id);
            return Result.ok().message("删除成功");
        }
        return Result.error().message("该角色已经关联,无法删除");
    }

    /**
     * 根据角色id删除角色信息
     *
     * @param roleId 角色id
     * @return
     */
    @Override
    public Integer delRoleByRoleId(Integer roleId) {
        QueryWrapper<MyRole> wrapper = new QueryWrapper<>();
        wrapper.eq("role_id", roleId);
        return roleMapper.delete(wrapper);
    }

    @Override
    public Result<MyRole> getAllRoles() {
        return Result.ok().data(roleMapper.selectList(null));
    }

    @Override
    public Integer updateRole(RoleVo myRole) {
        UpdateWrapper<MyRole> wrapper = new UpdateWrapper<>();
        if (!StringUtils.isEmpty(myRole.getRoleId())) {
            wrapper.eq("role_id", myRole.getRoleId());
        }
        if (!StringUtils.isEmpty(myRole.getRoleName())) {
            myRole.setRoleName(myRole.getRoleName());
        }
        myRole.setUpdateTime(now());
        return roleMapper.update(myRole, wrapper);
    }

}
